#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vector.h"

void v_expand(VECTOR_T * vector);

VECTOR_T * v_new(size_t capacity) {
	//Allocate memory for the vector
	VECTOR_T * vector = malloc(sizeof(VECTOR_T));
	
	//Initialize
	if (vector != NULL) {
		vector->current = -1;
		vector->capacity = capacity;
		vector->data = calloc(capacity, sizeof(VECTOR_T_DATA));
		
		//If the data allocation fails, free the vector and exit.
		if (vector->data == NULL) {
			fprintf(stderr, "In v_new : vector data array allocation failed.\n");
			free(vector);
			exit(1);
		} else {
			return vector;
		}
	} else {
		fprintf(stderr, "In v_new : struct VECTOR_T allocation failed.\n");
		exit(1);
	}
}

void v_add(VECTOR_T * vector, VECTOR_T_DATA data) {	
	vector->current++;
	if (vector->current == (int)vector->capacity) {
		// If the vector is full, allocate more memory
		v_expand(vector);
	}
	vector->data[vector->current] = data;
}

void v_set(VECTOR_T * vector, VECTOR_T_DATA data, int pos) {
	if (pos >= 0 && pos < vector->current) {
		vector->data[pos] = data;
	} else {
		fprintf(stderr, "In v_get : index out of bound.\n");
		exit(1);
	}
}

VECTOR_T_DATA v_get(VECTOR_T * vector, int pos) {
	if (pos >= 0 && pos < vector->current) {
		return vector->data[pos];
	} else {
		fprintf(stderr, "In v_get : index out of bound.\n");
		exit(1);
	}
}

VECTOR_T_DATA v_pop(VECTOR_T * vector) {
	if (vector->current >= 0) {
		VECTOR_T_DATA value = vector->data[vector->current];
		vector->current--;
		return value;
	} else {
		fprintf(stderr, "In v_pop : vector is empty, nothing to remove.\n");
		exit(1);
	}
}

VECTOR_T_DATA v_remove(VECTOR_T * vector, int pos) {
	VECTOR_T_DATA value = vector->data[pos];
	if (pos >= 0 && pos < vector->current) {
		memmove(vector->data + pos, vector->data + pos + 1, (vector->current - pos) * sizeof(VECTOR_T_DATA));
		vector->current--;
		return value;
	} else if (pos == vector->current) {
		vector->current--;
		return value;
	} else {
		fprintf(stderr, "In v_remove : index out of bound.\n");
		exit(1);
	}
}

int v_count(VECTOR_T * vector) {
	return vector->current;
}

int v_isempty(VECTOR_T * vector) {
	return vector->current == -1;
}

void v_clear(VECTOR_T * vector) {
	vector->current = -1;
}

void v_delete(VECTOR_T * vector) {
	free(vector->data);
	free(vector);
}

void v_expand(VECTOR_T * vector) {
	vector->capacity *= 2;
	VECTOR_T_DATA * old_data = vector->data;
	vector->data = realloc(vector->data, vector->capacity * sizeof(VECTOR_T_DATA));
	if (vector->data == NULL) {
		fprintf(stderr, "In v_expand : could not allocate more memory, vector overflow.\n");
		free(old_data);
		exit(1);
	}
}